﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using MockSchoolManagement.Core;
using MockSchoolManagement.Mvc.ViewModel;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;

namespace MockSchoolManagement.Mvc.Controllers
{
    [Authorize(Roles = "Admin")]
    public class AdminController : Controller
    {
        private readonly RoleManager<IdentityRole> _roleManager;
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly ILogger<AdminController> _logger;
        #region 角色管理

        public AdminController(RoleManager<IdentityRole> roleManager, UserManager<ApplicationUser> userManager, ILogger<AdminController> logger)
        {
            _roleManager = roleManager;
            _userManager = userManager;
            _logger = logger;
        }
        [HttpGet]
        public IActionResult CreateRole()
        {
            return View();
        }
        [HttpPost]
        public async Task<IActionResult> CreateRole(CreateRoleViewModel model)
        {
            if (ModelState.IsValid)
            {
                var role = new IdentityRole(model.RoleName);
                var result = await _roleManager.CreateAsync(role);
                if (result.Succeeded)
                {
                    return RedirectToAction("ListRole", "Admin");
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }

            return View();
        }
        [HttpGet]
        public IActionResult ListRole()
        {
            var roles = _roleManager.Roles;
            return View(roles);
        }
        [HttpGet]
        [Authorize(Policy = "EditRolePolicy")]
        public async Task<IActionResult> EditRole(string id)
        {
            var role = await _roleManager.FindByIdAsync(id);
            if (role == null)
            {
                ViewBag.ErrorMessage = $"角色ID为：{id}的信息不存在，请重试";
                return View("NotFound");
            }

            var editRole = new EditRoleViewModel()
            {
                Id = role.Id,
                RoleName = role.Name
            };
            var users = _userManager.Users.ToList();
            foreach (var user in users)
            {
                if (await _userManager.IsInRoleAsync(user, role.Name))
                {
                    editRole.User.Add(user.UserName);
                }
            }
            return View(editRole);
        }
        [HttpPost]
        public async Task<IActionResult> EditRole(EditRoleViewModel model)
        {
            if (ModelState.IsValid)
            {
                var role = await _roleManager.FindByIdAsync(model.Id);
                if (role == null)
                {
                    ViewBag.ErrorMessage = $"角色ID={model.Id}的信息不存在，请重试";
                    return View("NotFound");
                }
                else
                {
                    role.Name = model.RoleName;
                    var updateResult = await _roleManager.UpdateAsync(role);
                    if (updateResult.Succeeded)
                    {
                        return RedirectToAction("ListRole");
                    }

                    foreach (var error in updateResult.Errors)
                    {
                        ModelState.AddModelError(string.Empty, error.Description);
                    }
                }
            }

            return View(model);
        }
        [HttpPost]
        [Authorize(policy: "DeleteRolePolicy")]
        public async Task<IActionResult> DeleteRole(string id)
        {
            var role = await _roleManager.FindByIdAsync(id);
            if (role == null)
            {
                ViewBag.ErrorMessage = $"无法找到ID={id}的角色信息";
                return View("NotFound");
            }

            try
            {
                var result = await _roleManager.DeleteAsync(role);
                if (result.Succeeded)
                {
                    return RedirectToAction("ListRole");
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError(string.Empty, error.Description);
                }
            }
            //如果出发的异常是DbUpdateException，则知道我们无法删除角色，因为该角色中已存在用户信息
            catch (DbUpdateException ex)
            {
                _logger.LogError($"发生异常：{ex}");
                ViewBag.ErrorTitle = $"角色：{role.Name} 正在被使用中...";
                ViewBag.ErrorMessage = $"无法删除{role.Name}角色，因为此角色中已经存在用户。如果要删除此角色，需要先从该角色中删除用户，然后尝试删除该角色本身";
                return View("Error");
            }

            return View("ListRole");
        } 
        #endregion
        #region 用户角色管理

        [HttpGet]
        public async Task<IActionResult> EditUserInRole(string roleId)
        {
            ViewBag.RoleId = roleId;
            var role = await _roleManager.FindByIdAsync(roleId);
            if (role == null)
            {
                ViewBag.ErrorMessage = $"角色ID={roleId}的信息不存在";
                return View("NotFound");
            }

            var model = new List<UserRoleViewModel>();
            var users = _userManager.Users.ToList();
            foreach (var user in users)
            {
                var userRoleViewModel = new UserRoleViewModel()
                {
                    UserId = user.Id,
                    UserName = user.UserName
                };
                //判断当前用户是否已在角色当中
                var isInRole = await _userManager.IsInRoleAsync(user, role.Name);
                if (isInRole)
                {
                    userRoleViewModel.IsSelected = true;
                }
                else
                {
                    userRoleViewModel.IsSelected = false;
                }
                model.Add(userRoleViewModel);
            }

            return View(model);
        }
        [HttpPost]
        public async Task<IActionResult> EditUserInRole(List<UserRoleViewModel> models, string roleId)
        {
            var role = await _roleManager.FindByIdAsync(roleId);
            if (role == null)
            {
                ViewBag.ErroeMessage = $"角色ID={roleId}的信息不存在，请重试。";
                return View("NotFound");
            }

            foreach (var model in models)
            {
                var user = await _userManager.FindByIdAsync(model.UserId);
                IdentityResult identityResult = null;

                //检查当前UserId是否被选中，如果被选中，则添加到角色列表中去
                if (model.IsSelected && !(await _userManager.IsInRoleAsync(user, role.Name)))
                {
                    identityResult = await _userManager.AddToRoleAsync(user, role.Name);
                }//如果没有被选中，则从UserRole表中移除
                else if (!model.IsSelected && (await _userManager.IsInRoleAsync(user, role.Name)))
                {
                    identityResult = await _userManager.RemoveFromRoleAsync(user, role.Name);
                }
                else
                {
                    continue;
                }
            }
            return RedirectToAction("EditRole", new { Id = role.Id });
        }
        [HttpGet]
        [Authorize(policy:"EditRolePolicy")]
        public async Task<IActionResult> ManageUserRole(string id)
        {
            ViewBag.userId = id;
            var user =await _userManager.FindByIdAsync(id);
            if (user==null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{id}的用户";
                return View("NotFound");
            }

            var model = new List<RolesInUserViewModel>();
           // var roles = await _roleManager.Roles.ToListAsync();
            foreach (var role in _roleManager.Roles)
            {
                var roleInUserViewModel = new RolesInUserViewModel() {RoleId = role.Id, RoleName = role.Name};
                //判断当前用户是否已经拥有了该角色信息
                if (await _userManager.IsInRoleAsync(user,role.Name))
                {
                    //将已拥有的角色信息设置为选中
                    roleInUserViewModel.IsSelected = true;
                }

                roleInUserViewModel.IsSelected = false;
                model.Add(roleInUserViewModel);
            }

            return View(model);
        }
        [HttpPost]
        public async Task<IActionResult> ManageUserRole(List<RolesInUserViewModel> models, string userId)
        {
            var user = await _userManager.FindByIdAsync(userId);
            if (user==null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{userId}的用户";
                return View("NotFound");
            }

            var roles = await _userManager.GetRolesAsync(user);
            //移除当前用户中的所有角色信息
            var result = await _userManager.RemoveFromRolesAsync(user, roles);

            if (!result.Succeeded)
            {
                ModelState.AddModelError(string.Empty,"无法删除用户中的现有角色");
                return View(models);
            }
            //查询模型列表中被选中的RoleName并添加到用户中
            result = await _userManager.AddToRolesAsync(user, models.Where(x => x.IsSelected).Select(x => x.RoleName));
            if (!result.Succeeded)
            {
                ModelState.AddModelError(string.Empty,"无法向用户添加选定的角色");
                return View(models);
            }

            return RedirectToAction("EditUser", new {Id = userId});
        }

        #endregion

        #region 用户管理
        [HttpGet]
        public IActionResult ListUser()
        {
            var users=_userManager.Users.ToList();
            return View(users);
        }
        [HttpGet]
        public async Task<IActionResult> EditUser(string id)
        {
            var user =await _userManager.FindByIdAsync(id);
            if (user==null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{id}的用户";
                return View("NotFound");
            }

            //GetClaimsAsync()返回用户声明列表
            var userClaims = await _userManager.GetClaimsAsync(user);
            //GetRolesAsync()返回用户角色列表
            var userRoles = await _userManager.GetRolesAsync(user);

            var model = new EditUserViewModel()
            {
                Id = user.Id,
                Email = user.Email,
                City = user.City,
                UserName = user.UserName,
                Claims = userClaims,
                Roles = userRoles
            };
            return View(model);
        }
        [HttpPost]
        public async Task<IActionResult> EditUser(EditUserViewModel model)
        {
            var user = await _userManager.FindByIdAsync(model.Id);
            if (user==null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{model.Id}的用户";
                return View("NotFound");
            }

            user.City = model.City;
            user.Email = model.Email;
            user.UserName = model.UserName;

            var result= await _userManager.UpdateAsync(user);
            if (result.Succeeded)
            {
                return RedirectToAction("ListUser", "Admin");
            }

            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty,error.Description);
            }

            return View(model);

        }
        [Authorize(Policy = "SuperAdminPolicy")]
        [HttpPost]
        public async Task<IActionResult> DeleteUser(string id)
        {
            var user = await _userManager.FindByIdAsync(id);
            if (user==null)
            {
                ViewBag.ErrorMessage = $"用户Id={id}的用户不存在，请重试。";
                return View("NotFound");
            }

            var result= await _userManager.DeleteAsync(user);
            if (result.Succeeded)
            {
                return RedirectToAction("ListUser");
            }

            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty,error.Description);
            }

            return View("ListUser");
        }

        [HttpGet]
        public async Task<IActionResult> ManageUsrClaims(string id)
        {
            var user = await _userManager.FindByIdAsync(id);
            if (user == null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{id}的用户";
                return View("NotFound");
            }

            var existingUserClaims = await _userManager.GetClaimsAsync(user);

            var model = new UserClaimsViewModel()
            {
                UserId = user.Id
            };

            foreach (var claim in ClaimsStore.AllClaims)
            {
                UserClaim userClaim = new UserClaim()
                {
                    ClaimType = claim.Type
                };

                //如果用户选中了声明属性，则设置IsSelect属性为True
                if (existingUserClaims.Any(c => c.Type == claim.Type))
                {
                    userClaim.IsSelected = true;
                }

                model.Claims.Add(userClaim);
            }

            return View(model);
        }
        [HttpPost]
        public async Task<IActionResult> ManageUsrClaims(UserClaimsViewModel model)
        {
            var user = await _userManager.FindByIdAsync(model.UserId);
            if (user == null)
            {
                ViewBag.ErrorMessage = $"无法找到ID为{model.UserId}的用户";
                return View("NotFound");
            }
            //获取所有用户现有的声明并删除他们
            var claims = await _userManager.GetClaimsAsync(user);
            var result = await _userManager.RemoveClaimsAsync(user, claims);

            if (!result.Succeeded)
            {
                ModelState.AddModelError(string.Empty,"无法删除当前用户的声明");
                return View(model);
            }

            //添加页面上选中的所有声明信息
            result = await _userManager.AddClaimsAsync(user,
                model.Claims.Select(c => new Claim(c.ClaimType, c.IsSelected?"True":"False")));

            if (!result.Succeeded)
            {
                ModelState.AddModelError(string.Empty,"无法向用户添加选定的声明");
                return View(model);
            }

            return RedirectToAction("EditUser", new {Id = model.UserId});
        }
        #endregion
        [HttpGet]
        public IActionResult AccessDenied()
        {
            return View();
        }
    }
}
